home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Mac Game Programming Gurus / TricksOfTheMacGameProgrammingGurus.iso / More Source / Pascal / sndDemo / sndDemo.p < prev    next >
Text File  |  1995-06-15  |  7KB  |  173 lines

  1. program sndDemo;
  2.  
  3. { I spent a hard week getting this demo of the playing of an asynchronous sound to work }
  4. { in Think Pascal 4.0.2. My main difficulty was that it won't work with the [D] Debug switch set }
  5. { on the compile options. But the manual doesn't contain all of the necessary information.  }
  6. { Some essential ideas were gleaned from Jim Reekes' pSoundApp example in the DTS folder }
  7. { of ftp.apple.com.  Since it was so touchy, I thought others might benefit from this demo. }
  8. {  }
  9. { This code is terse. I have stripped out everything but the essentials. It should be used }
  10. { in conjuntion with chapter 22 of volume VI of Inside Macintosh. I have deliberately left }
  11. { out all error checking so as to not obscure the essential code. Although in all my testing }
  12. { I never saw an error that wasn't a result of my stupidity or ignorance. I have included a }
  13. { few extra inline procedure declarations to make it easier to build this demo into a real program. }
  14. {  }
  15. { To play an asynchronous sound - that is, a sound that plays while other things are happening, }
  16. { one must define a callBack procedure. This procedure can't do much because it will be invoked }
  17. { at interrupt time and won't have access to your normal program environment. To access your }
  18. { global variables, you must restore register A5. Most of the callBack code is concerned with }
  19. { restoring A5; and all the callback procedure does is set a switch 'sndProgress := 2' so that you }
  20. { can tell (elsewhere) that the sound has finished. }
  21. {  }
  22. { Two global variables are needed: }
  23. { - The integer sndProgress is meant to have the value 0 when no sound is playing, 1 when a sound}
  24. {    is playing, and 2 when a sound has finished but the resources haven't been released yet. }
  25. { - The sndChannelPtr mySndChannel is given a value when a sound channel is allocated in the }
  26. {    routine that starts the sound playing (aSyncStartPlay), and is needed to dispose of the channel }
  27. {    when the sound has completed and must be disposed (aSyncEndPlay). }
  28. {  }
  29. { If you use these routines to play async sounds, you will want a line of code in your main}
  30. { event loop to dispose of the channel and sound handle as soon as the sound has completed:}
  31. {           if sndProgress = 2 then                }
  32. {                aSyncEndPlay(sndChannel);     }
  33. {  }
  34. { What this demo program does, is start the sound playing and then count until the sound is done. }
  35. { The count is written to the text window. It does this five times. You must open the window manually }
  36. { and place it strategically if you want to watch the counting as the sound is played. }
  37. { ------------------------------------------------------------------------------------------ }
  38. { Marv Westrom }
  39. { Mathematics and Science Education (Computing Studies Education) }
  40. { The University of British Columbia }
  41. { Vancouver, B.C.   Canada    V6T 1Z4 }
  42. { ------------------------------------------------------------------------------------------ }
  43. { March 24, 1993.}
  44. { ------------------------------------------------------------------------------------------ }
  45.  
  46. {--- Changes by Ingemar Ragnemalm june 1994. ---}
  47. {}
  48. {All I've done is to change capitalization of some constant and procedure names to conform better to the}
  49. { standards of Mac programming: procedures and types first letter upper-case, variables and constants}
  50. { not, constants should start with "k", globals variables with "g". How "integer" and "longint" should look,}
  51. { I'm not 100% sure - everybody does it different, it seems.}
  52. {}
  53. { I also compressed the sound 3:1, making the total archive REALLY small.}
  54. {}
  55. {A little warning: This code seems quite ok, but you may want to know a few things when using it:}
  56. {- You don't really have to have a callback procedure, if you don't care exactly when the previous sound}
  57. {finishes playing. Even then, you can use SndChannelStatus instead. You can stop the previous sound by}
  58. {disposing the channel.}
  59. {- You will get more speed if you don't dispose the channel after every sound, BUT that will increase}
  60. {the risk of crashes when using Sound Manager older than version 3.0 (and there are LOTS of Macs}
  61. {that aren't updated yet!!!) So if you want to get speed up, beware… Of course, some take the easy way}
  62. {out and don't guarantee anything with old SM.}
  63. {}
  64. {Finally, including Sound.p in the project, and "uses Sound" in the beginning, is usually preferrable over}
  65. {copying in a bunch of the declarations.}
  66.  
  67.     uses
  68. {$IFC UNDEFINED THINK_PASCAL}
  69.         Types, QuickDraw, Events, Menus, Dialogs, Fonts, Resources, Devices, 
  70. {$ENDC}
  71.         Sound;
  72.  
  73.     const
  74.         kNoSynth = 0;        { no specified synth for channel }
  75.         kInitNone = 0;            { no specified init parameters for channel }
  76.  
  77.     var { necessary globals }
  78.         gMySndChannel: SndChannelPtr;
  79.         gSndProgress: integer;
  80.  
  81. {$PUSH}
  82. {$D-}
  83.     procedure MyCallBack (Chan: sndChannelPtr; cmd: sndCommand);
  84.         var
  85.             myA5: longint;
  86.     begin
  87.         if cmd.param1 = 99 then
  88.             begin
  89.                 myA5 := SetA5(cmd.param2);
  90.                 gSndProgress := 2;
  91.                 myA5 := SetA5(myA5);
  92.             end;
  93.     end;
  94. {$POP}
  95.  
  96.     procedure AsyncStartPlay (sndH: handle);
  97.         var
  98.             mySndCmd: sndCommand;
  99.             myErr: OSErr;
  100.     begin
  101.         LoadResource(sndH);
  102.         MoveHHi(sndH);
  103.         Hlock(sndH);
  104.         gMySndChannel := nil;
  105.         myErr := SndNewChannel(gMySndChannel, kNoSynth, kInitNone, @MyCallBack);
  106. {$IFC UNDEFINED THINK_PASCAL}
  107.         myErr := SndPlay(gMySndChannel, SndListHandle(sndH), true);
  108. {$ELSEC}
  109.         myErr := SndPlay(gMySndChannel, sndH, true);
  110. {$ENDC}
  111.         gSndProgress := 1;
  112.         mySndCmd.cmd := 13;                    { callBackCmd }
  113.         mySndCmd.param1 := 99;                { arbitrary code to check MyCallback }
  114.         mySndCmd.param2 := SetCurrentA5;
  115.         myErr := SndDoCommand(gMySndChannel, mySndCmd, false);
  116.     end;
  117.  
  118.     procedure AsyncEndPlay (sndH: handle);
  119.         var
  120.             mySndCmd: sndCommand;
  121.             myErr: OSErr;
  122.     begin
  123.         mySndCmd.cmd := 3;        { quietCmd }
  124.         myErr := SndDoCommand(gMySndChannel, mySndCmd, false);
  125.         myErr := SndDisposeChannel(gMySndChannel, true);
  126.         HUnlock(sndH);
  127.         gSndProgress := 0;
  128.     end;
  129.  
  130.     procedure InitMacintosh;
  131.     begin
  132. {$IFC UNDEFINED THINK_PASCAL}
  133.         MaxApplZone;
  134.  
  135.         InitGraf(@qd.thePort);
  136.         InitFonts;
  137.         FlushEvents(everyEvent, 0);
  138.         InitWindows;
  139.         InitMenus;
  140.         TEInit;
  141.         InitDialogs(nil);
  142. {$ENDC}
  143.         InitCursor;
  144.     end; {InitMacintosh}
  145.  
  146. {Variables that are local to the main procedure.}
  147.     var
  148.         sndHiThere: Handle;
  149.         i, times: integer;
  150.  
  151. begin
  152.     InitMacintosh;
  153.  
  154.     gSndProgress := 0;
  155.     sndHiThere := GetNamedResource('snd ', 'Hi There');
  156. {$IFC DEFINED THINK_PASCAL}
  157.     ShowText;
  158. {$ENDC}
  159.     for times := 1 to 5 do
  160.         begin
  161.             writeln;
  162.             writeln('Hi there ', times : 2);
  163.             AsyncStartPlay(sndHiThere);
  164.             i := 0;
  165.             repeat
  166.                 i := i + 1;
  167.                 write(i : 3);
  168.                 if (i mod 25) = 0 then
  169.                     writeln;
  170.             until gSndProgress = 2;
  171.             AsyncEndplay(sndHiThere);
  172.         end;
  173. end.